package org.JQbitorrentClinet.base;

import lombok.*;
import org.JQbitorrentClinet.utils.HttpClientProxyRequestType;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

@Data
@AllArgsConstructor
public abstract class BaseParam {

    @Setter(AccessLevel.PROTECTED)
    protected Type responseType = String.class;
    @Setter(AccessLevel.PROTECTED)
    protected HttpClientProxyRequestType requestType = HttpClientProxyRequestType.GET;

    public BaseParam() {
    }

    public Map<String, Object> getParamMap() throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        Field[] allFields = this.getClass().getDeclaredFields();
        for (Field field : allFields) {
            if (!isBaseParamField(field)) {
                field.setAccessible(true);
                Object value = field.get(this);
                if (value != null) {
                    value = InternalGetConvertedValue(field);
                    map.put(field.getName(), value);
                }
            }
        }
        return map;
    }

    @SneakyThrows
    private Object InternalGetConvertedValue(Field field)
    {
        Object value = field.get(this);

        if(field.getType() == String[].class)
        {
            switch (field.getName()) {
                case "hashes":
                case "sources":
                case "names":
                case "peers":
                case "indexes":
                case "id":
                case "plugins":
                    value = String.join("|", (String[]) value);
                    break;
                case "tags":
                    value = String.join(",", (String[]) value);
                    break;
                case "urls":
                case "categories":
                    value = String.join("\n", (String[]) value);
                    break;
            }
        }

        if (field.getType() == Boolean.class)
            value = value.toString().toLowerCase();

        return value;
    }

    private boolean isBaseParamField(Field field) {
        try {
            BaseParam.class.getDeclaredField(field.getName());
            return true;
        } catch (NoSuchFieldException e) {
            return false;
        }
    }

    public abstract String getApiUrl();
}
